package app.models.transfer;

import app.Const;
import app.constant.TransferConstant;
import app.kit.CommonKit;
import app.kit.TypeKit;
import app.services.profit.ProfitService;
import com.google.common.base.Strings;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import goja.annotation.TableBind;
import goja.plugins.sqlinxml.SqlKit;
import goja.rapid.db.RequestParam;
import goja.tuples.Pair;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import static app.Const.FIELD_AMOUNT;
import static app.Const.FIELD_TIME_LIMIT_UNIT;
import static app.Const.FIELD_YIELD;
import static app.constant.TransferConstant.STATUE_SUCCESS;
import static app.constant.TransferConstant.STATUE_TRADING;

/**
 * <p>
 * The database rlt_product Model.
 * </p>
 *
 * @author sagyf yang
 * @version 1.0
 * @since JDK 1.6
 */
@TableBind(tableName = "rlt_product")
public class TransferProduct extends Model<TransferProduct> {

    /**
     * The public dao.
     */
    public static final TransferProduct dao = new TransferProduct();

    private static final long serialVersionUID = 175030399628671168L;

    public boolean audit(String id) {
        int update = Db.update(SqlKit.sql("transfer_product.audit"), id);
        return update > 0;
    }

    /**
     * 关联查询出转让产品、转让形式
     * @param id 转让产品表中 id
     * @return
     */
    public Record getPrdtAndMdlById(String id) {
        return Db.findFirst(SqlKit.sql("transfer_product.getPrdtAndMdlById"), id);
    }

    /**
     * 查询转让产品表，用于市场展示，需要考虑状态问题.
     *
     * @param page 页码
     * @return 转让产品列表
     */
    public List<TransferProduct> findByMarket(int page) {
        int offset = (page - 1) * Const.PAGE;
        int rows = Const.PAGE;
        return find(SqlKit.sql("transfer_product.findByMarket"), STATUE_TRADING, offset, rows);
    }

    /**
     * 转让产品详情
     *
     * @param id 产品ID
     * @return 转让产品详情
     */
    public TransferProduct findByInfo(int id) {
        return findFirst(SqlKit.sql("transfer_product.findByInfo"), id);
    }

    public int findAvailableCount() {
        TransferProduct first = findFirst(SqlKit.sql("transfer_product.findAvailableCount"));
        return TypeKit.getInt(first, "cnt");
    }

    /**
     * 计算昨日统计
     *
     * @return 昨日统计数据
     */
    public TransferProduct findByYesterdayCount() {
        DateTime yester = DateTime.now().plusDays(-1);
        final DateTime begin = yester.millisOfDay().withMinimumValue();
        final DateTime end = yester.millisOfDay().withMaximumValue();
        return findFirst(SqlKit.sql("transfer_product.findByYesterdayCount"), begin.toDate(), end.toDate(), STATUE_SUCCESS);
    }

    public TransferProduct findByAllCount() {
        return findFirst(SqlKit.sql("transfer_product.findByAllCount"), STATUE_SUCCESS);
    }

    /**
     * 转让市场展示
     *
     * @param page           页码
     * @param pageSize       每页现实
     * @param sort_field     排序
     * @param direction 排序方向
     * @return 数据
     */
    public Page<TransferProduct> findByPageList(int page, int pageSize, String sort_field, RequestParam.Direction direction) {
        final Pair<Integer, Integer> offsets = CommonKit.pageOffset(page, pageSize);
        String order_sql = "tp.put_time DESC";
        if (!Strings.isNullOrEmpty(sort_field)) {
            order_sql = "tp." + sort_field + " " + direction.toString();
        }
        final String count_sql = SqlKit.sql("transfer_product.pageListCount");
        TransferProduct count_prod = findFirst(count_sql);

        final long total = TypeKit.getLong(count_prod, "cnt");
        if(total == 0){
            return new Page<TransferProduct>(Collections.EMPTY_LIST, page, pageSize, 0, 0);
        }


        String sql = String.format(SqlKit.sql("transfer_product.findByPageList"), order_sql);
        List<TransferProduct> products = find(sql, TransferConstant.STATUE_TRADING,STATUE_SUCCESS,offsets.getValue1(), offsets.getValue0());

        int totalPage = (int) total / pageSize;
        if (total % pageSize != 0) {
            totalPage++;
        }

        return new Page<TransferProduct>(products, page, pageSize, totalPage, (int) total);
    }

    public TransferProduct findByAllInfo(long transferId) {
        return findFirst(SqlKit.sql("transfer_product.findByAllInfo"), transferId);
    }

    /**
     * 查找在售的并且挂单时间+24小时超过当前时间的
     * @param aging    转让时效
     * @return 转让产品
     */
    public List<TransferProduct> findOverdue(int aging) {
        return find(SqlKit.sql("transfer_product.findOverdue"), STATUE_TRADING, aging);
    }

    /**
     * 获取首页的转让数据，交易中的 按时间
     * @return 转让数据
     */
    public List<TransferProduct> homeDisplay() {
        return find(SqlKit.sql("transfer_product.homeDisplay"), STATUE_TRADING, STATUE_SUCCESS);
    }

    public TransferProduct findByMemberProduct(int memberProductId,int productId) {
        return findFirst(SqlKit.sql("transfer_product.findByMemberProduct"), memberProductId, productId, STATUE_TRADING);
    }


    /**
     * 将正在交易的数据更新为指定的状态
     * @param productId 产品ID
     * @param status 待更新状态
     * @return 是否更新成功
     */
    public boolean updateStatusByProduct(int productId, int status){
        return Db.update(SqlKit.sql("transfer_product.updateStatusByProduct"),status ,productId , TransferConstant.STATUE_TRADING) >=0;
    }

    public TransferProduct findByMemberProductDetail(long memberProductId, int status){
        return findFirst(SqlKit.sql("transfer_product.findByMemberProductDetail"), memberProductId, status);
    }

    public BigDecimal profit() {
            // 计算预期收益
        int time_unit = TypeKit.getInt(this, "time_limit");
        String time_limit_unit = this.getStr(FIELD_TIME_LIMIT_UNIT);
        int hold_days = CommonKit.termDays(time_unit, time_limit_unit, TypeKit.getDateTime(this, "product_valuedate"));

            return ProfitService.me.onceProfit(this.getBigDecimal(FIELD_AMOUNT),
                    this.getBigDecimal(FIELD_YIELD), TypeKit.getInt(this, "basic_days"), hold_days);

    }
}